package com.jinyang.jetpackdemo.util

import android.annotation.TargetApi
import android.app.Activity
import android.content.Context
import android.os.Build
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.lifecycleScope
import com.jinyang.jetpackdemo.util.application.ApplicationUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import java.io.Serializable

/**
 * @Author:         LiuJinYang
 * @CreateDate:     2021/11/24
 * @Description:
 */
class PermissionUtil private constructor() : Serializable {

    private fun readResolve(): Any {
        return instance
    }

    companion object {
        @JvmStatic
        val instance: PermissionUtil by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { PermissionUtil() }
    }

    private val permissionFragment: PermissionFragment = PermissionFragment()

    fun permissionsRequest(
        activity: FragmentActivity,
        permissions: Array<String>,
        callBack: (allGranted: Boolean) -> Unit
    ) {
        permissionFragment.permissions = permissions
        permissionFragment.callBack = callBack
        val fragmentTransaction = activity.supportFragmentManager.beginTransaction()
        if (permissionFragment.isAdded) {
            permissionFragment.removeFragment()
        }
        fragmentTransaction.add(permissionFragment, "permissionFragment@LJY").commit()
    }

    fun permissionsRequest(permissions: Array<String>, callBack: (allGranted: Boolean) -> Unit) {
        val context: Activity = ApplicationUtil.instance.getTopActivity()
            ?: throw java.lang.NullPointerException("Top Activity is Null!")
        permissionsRequest(context as FragmentActivity, permissions, callBack)
    }

    class PermissionFragment : Fragment() {
        private lateinit var requestMultiplePermissionsLauncher:
                ActivityResultLauncher<Array<String>>
        var permissions: Array<String>? = null
        var callBack: ((Boolean) -> Unit)? = null

        fun removeFragment() {
            val fragmentTransaction: FragmentTransaction = parentFragmentManager.beginTransaction()
            fragmentTransaction.remove(this).commit()
        }


        override fun onAttach(context: Context) {
            super.onAttach(context)
            requestMultiplePermissionsLauncher =
                registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { it ->
                    //通过的权限
                    val grantedList = it.filterValues { it }.mapNotNull { it.key }
                    //是否所有权限都通过
                    val allGranted = grantedList.size == it.size
                    val list = (it - grantedList.toSet()).map { it.key }
                    //未通过的权限
                    val deniedList =
                        list.filter {
                            ActivityCompat.shouldShowRequestPermissionRationale(
                                requireActivity(),
                                it
                            )
                        }
                    //拒绝并且点了“不再询问”权限
                    val alwaysDeniedList = list - deniedList.toSet()
                    callBack?.invoke(allGranted)
                    removeFragment()
                }
            if (permissions?.isNotEmpty() == true)
                requestMultiplePermissionsLauncher.launch(permissions)
        }
    }


}

class PermissionsFragment : Fragment() {
    private val PERMISSIONS_REQUEST_CODE = 520
    var permissions: Array<String>? = null
    var callBack: ((Boolean) -> Unit)? = null

    fun removeFragment() {
        val fragmentTransaction: FragmentTransaction = parentFragmentManager.beginTransaction()
        fragmentTransaction.remove(this).commit()
    }

    @TargetApi(Build.VERSION_CODES.M)
    fun requestPermissions(permissions: Array<String?>) {
        requestPermissions(
            permissions,
            PERMISSIONS_REQUEST_CODE
        )
    }

    @TargetApi(Build.VERSION_CODES.M)
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    }
}


val permissionFragment: PermissionFragment = PermissionFragment()

/**
 * 所有权限统一返回结果
 */
fun permissionsRequest(
    activity: FragmentActivity,
    permissions: Array<String>,
    accept: (allGranted: Boolean) -> Unit
) {
    permissionFragment.permissions = permissions
    permissionFragment.accept = accept
    val fragmentTransaction = activity.supportFragmentManager.beginTransaction()
    fragmentTransaction.add(permissionFragment, "permissionFragment@LJY").commit()
}

/**
 * 所有权限统一返回结果
 */
fun permissionsRequest(permissions: Array<String>, accept: (allGranted: Boolean) -> Unit) {
    val context: Activity = ApplicationUtil.instance.getTopActivity()
        ?: throw java.lang.NullPointerException("Top Activity is Null!")
    permissionsRequest(context as FragmentActivity, permissions, accept)
}

/**
 * 将权限申请结果逐一返回
 */
fun permissionsRequestEach(
    activity: FragmentActivity,
    permissions: Array<String>,
    permissionResult: (Permission) -> Unit
) {
    permissionFragment.permissions = permissions
    permissionFragment.permissionResult = permissionResult
    val fragmentTransaction = activity.supportFragmentManager.beginTransaction()
    fragmentTransaction.add(permissionFragment, "permissionFragment@LJY").commit()
}

/**
 * 将权限申请结果逐一返回
 */
fun permissionsRequestEach(permissions: Array<String>, permissionResult: (Permission) -> Unit) {
    val context: Activity = ApplicationUtil.instance.getTopActivity()
        ?: throw java.lang.NullPointerException("Top Activity is Null!")
    permissionsRequestEach(context as FragmentActivity, permissions, permissionResult)
}

data class Permission(
    var name: String?,
    var granted: Boolean,
    var shouldShowRequestPermissionRationale: Boolean
)

class PermissionFragment : Fragment() {
    private lateinit var requestMultiplePermissionsLauncher:
            ActivityResultLauncher<Array<String>>
    var permissions: Array<String>? = null
    var accept: ((Boolean) -> Unit)? = null
    var permissionResult: ((Permission) -> Unit)? = null
    var denied: ((String) -> Unit)? = null
    var alwaysDenied: ((String) -> Unit)? = null

    fun removeFragment() {
        val fragmentTransaction: FragmentTransaction = parentFragmentManager.beginTransaction()
        fragmentTransaction.remove(this).commit()
    }


    override fun onAttach(context: Context) {
        super.onAttach(context)
        requestMultiplePermissionsLauncher =
            registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { it ->

                lifecycleScope.launch {
                    //是否所有权限都通过
                    val allGranted = it.iterator()
                        .asFlow()
                        .flowOn(Dispatchers.Main)
                        .map { it.value }
                        .reduce { a, b ->
                            a && b
                        }
                    accept?.invoke(allGranted)
                    it.iterator()
                        .asFlow()
                        .flowOn(Dispatchers.Main)
                        .onEach { entry ->
                            log("所有权限:" + entry.key)
                            permissionResult?.invoke(
                                Permission(
                                    entry.key,
                                    entry.value,
                                    ActivityCompat.shouldShowRequestPermissionRationale(
                                        requireActivity(),
                                        entry.key
                                    )
                                )
                            )
                        }
                        .filter { !it.value }
                        .onEach { entry ->
                            log("拒绝的权限:" + entry.key)
                            denied?.invoke(entry.key)
                        }
                        .filter {
                            !ActivityCompat.shouldShowRequestPermissionRationale(
                                requireActivity(),
                                it.key
                            )
                        }
                        .onEach { entry ->
                            log("拒绝并且点了“不再询问”的权限:" + entry.key)
                            alwaysDenied?.invoke(entry.key)
                        }
                        .collect()
                    if (isAdded) {
                        removeFragment()
                    }
                }

            }
        if (permissions?.isNotEmpty() == true)
            requestMultiplePermissionsLauncher.launch(permissions)
    }
}
